﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Timers;

namespace TouchControls
{
    internal enum MenuFlow
    {
        Unknown,
        None,
        Left,
        Top,
        Right,
        Bottom
    }

    internal class TouchMenuContainer : TouchMenuItem
    {
        private object lockobj = new object();

        internal TouchMenu ParentMenu { get; set; }

        private Timer _stbTimeout = new Timer();

        private Storyboard _stbHide;

        private bool _closed;

        public bool Closing
        {
            get
            {
                return _closed;
            }
        }

        public MenuFlow Flow { get; set; }

        private Grid _lockup;

        private AdornmentGrid _adornment;

        /// <summary>
        /// Timeout of menu in seconds
        /// </summary>
        public double Timeout
        {
            get { return (double)GetValue(TimeoutProperty); }
            set { SetValue(TimeoutProperty, value); }
        }

        public override Visibility HasItemsVisibility
        {
            get { return Visibility.Collapsed; }
            set
            {
                SetValue(HasItemsVisibilityProperty, Visibility.Collapsed);
            }
        }

        // Using a DependencyProperty as the backing store for Timeout.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TimeoutProperty =
            DependencyProperty.Register("Timeout", typeof(double), typeof(TouchMenuContainer), new PropertyMetadata(2.0));


        //protected override void OnMouseUp(System.Windows.Input.MouseButtonEventArgs e)
        //{            
        //    ParentMenu.RemoveContainer();
        //    base.OnMouseUp(e);
        //}

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            this.ItemButton.Opacity = 0.3;
            this.ApplyButtonPosition(ButtonRect);
        }

        public void SetContext(FrameworkElement triggerElt)
        {
            DataContext = triggerElt.DataContext;
        }

        public void AddToAdornment(AdornmentGrid adornment, FrameworkElement triggerElt)
        {            
            if (_stbHide != null)
            {
                this.StopHideStoryBoard();
            }
            ResetItems();
            Flow = MenuFlow.Unknown;
            _closed = false;
            _adornment = adornment;
            _adornment.Adornment.Children.Clear();
            _lockup = new Grid();
            _lockup.Background = new SolidColorBrush(Colors.Transparent);
            _lockup.Width = _adornment.RenderSize.Width;
            _lockup.Height = _adornment.RenderSize.Height;
            _adornment.Adornment.Children.Add(_lockup);

            this._adornment.Adornment.Children.Add(this);
            var position = triggerElt.TransformToAncestor(this._adornment).Transform(new Point());
            PositionMainButton(position, triggerElt.RenderSize);

            MinWidth = this.RenderSize.Width;
            MinHeight = this.RenderSize.Height;
            //_container.Background = new SolidColorBrush(Colors.Red);
            this._adornment.Adornment.AddHandler(UIElement.MouseUpEvent, new MouseButtonEventHandler(this.CanvasMouseUp));
            _adornment.Adornment.AddHandler(UIElement.TouchUpEvent, new EventHandler<TouchEventArgs>(Adornment_TouchUp));
            IsMenuOpened = true;
            this.StartTimeout();
        }        

        internal void RemoveFromDuty()
        {

            //while (this._container.Items.Count > 0)
            //{
            //    var elt = this._container.Items[0];
            //    var menu = elt as TouchMenuItem;
            //    if (menu != null)
            //    {
            //        menu.CloseMenu();
            //    }
            //    this._container.Items.Remove(elt);
            //    this.Items.Add(elt);
            //}
            this._adornment.Adornment.Children.Remove(this);
            this._adornment.Adornment.Children.Remove(this._lockup);
            //this._container = null;                

            _adornment.Adornment.RemoveHandler(UIElement.MouseUpEvent, new MouseButtonEventHandler(CanvasMouseUp));
            _adornment.Adornment.RemoveHandler(UIElement.TouchUpEvent, new EventHandler<TouchEventArgs>(Adornment_TouchUp));
        }

        void Adornment_TouchUp(object sender, TouchEventArgs e)
        {
            if (Animating)                 
                return;

            //this.HideContainer();
            if (_stbTimeout == null && !_closed)
            {
                StartTimeout();
            }
            else if (_closed || (!_stbTimeout.Enabled))
            {
                this.StopTimeout();
                this.HideContainer();
            }
        }

        private void CanvasMouseUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            if (Animating)
                return;

            //this.HideContainer();
            if (_stbTimeout == null && !_closed)
            {
                StartTimeout();
            }
            else /*if (_closed || (!_stbTimeout.Enabled))*/
            {
                this.StopTimeout();
                this.HideContainer();
            }
        }

        private void StartTimeout()
        {
            lock (lockobj)
            {
                if (_closed || _stbTimeout.Enabled) return;

                _stbTimeout.Interval = Timeout * 1000;
                _stbTimeout.Elapsed += new ElapsedEventHandler(Timeout_Elapsed);
                //_stbTimeout.Duration = new Duration(TimeSpan.FromSeconds(5));
                //_stbTimeout.Completed += new EventHandler(Timeout_Completed);
                _stbTimeout.Enabled = true;
            }
        }

        public void DelayTimeout()
        {
            this.StopTimeout();
            this.StartTimeout();
        }
        public void StopTimeout()
        {
            lock (lockobj)
            {
                _stbTimeout.Enabled = false;
            }
        }

        void Timeout_Elapsed(object sender, ElapsedEventArgs e)
        {
            lock (lockobj)
            {
                _closed = true;
                StopTimeout();
                HideContainer();
            }
        }

        void Timeout_Completed(object sender, EventArgs e)
        {

        }

        public void HideContainer()
        {
            this.StopTimeout();
            _closed = true;
            if (_stbHide != null) 
                return;
            Dispatcher.BeginInvoke(new Action(() =>
                {
                    _adornment.Children.Remove(_lockup);
                    
                    _stbHide = new Storyboard();
                    _stbHide.Completed += new EventHandler(stbHide_Completed);
                    _stbHide.Duration = new Duration(TimeSpan.FromSeconds(0.25));
                    DoubleAnimation animOpacity = new DoubleAnimation();
                    //animOpacity.Duration = _stbHide.Duration;
                    animOpacity.From = 0.6;
                    animOpacity.To = 0;
                    Storyboard.SetTarget(animOpacity, this);
                    Storyboard.SetTargetProperty(animOpacity, new PropertyPath(UIElement.OpacityProperty.Name));
                    _stbHide.Children.Add(animOpacity);
                    _stbHide.Begin();
                }));
        }

        void stbHide_Completed(object sender, EventArgs e)
        {
            if (_stbHide != null)
            {
                this.StopHideStoryBoard();
            }
            this.RemoveFromDuty();
        }

        private void StopHideStoryBoard()
        {
            lock (lockobj)
            {
                this._stbHide.Stop();
                this._stbHide.Children.Clear();
                this._stbHide.Completed -= new EventHandler(this.stbHide_Completed);
                this._stbHide = null;
            }
        }

        //public void StopTimeout()
        //{
        //    lock (lockobj)
        //    {
        //        if (this._stbTimeout != null)
        //        {
        //            var stb = _stbTimeout;
        //            _stbTimeout = null;
        //            stb.Enabled = false;
        //            stb.Completed -= new EventHandler(this.Timeout_Completed);
        //        }
        //    }
        //}

        protected override void ItemButtonClick(object sender, RoutedEventArgs e)
        {
            StartTimeout();
        }

        protected override void SelectionState(FrameworkElement elt, SelectionStates state)
        {
            if (elt == this)
            {
                base.SelectionState(elt, SelectionStates.InactiveParent);
                return;
            }

            if (state == SelectionStates.Children)
            {
                base.SelectionState(elt, SelectionStates.Active);
                return;
            }

            base.SelectionState(elt, state);
        }
    }
}
